package org.xserver.component.handler.ext;

import java.util.HashMap;
import java.util.Map;

import org.jboss.netty.channel.Channel;
import org.xserver.component.annotation.Path;
import org.xserver.component.core.Request.RequestType;
import org.xserver.component.core.XServerHttpContextAttachment;
import org.xserver.component.core.interfaces.InterfaceContext;
import org.xserver.component.core.interfaces.InterfaceMeta;
import org.xserver.component.handler.ext.http.HttpResponseWriteHandler;
import org.xserver.component.handler.ext.http.HttpResponseWriterHandlerFactory.HttpResponseType;
import org.xserver.component.handler.ext.websocket.WebsocketWriteHandler;
import org.xserver.component.prototype.annotation.ResponsePrototype;

/**
 * The {@code WriteHandler} factory, shall we config this in xml?. Now we just
 * config all {@link WriteHandler} in {@link ResponseType}
 * 
 * @author idoldefine
 * @since 2016/06/16
 *
 */
public class WriteHandlerFactory {
	private InterfaceContext interfaceContext;

	public Map<String, WriteHandler> writeHandlerInfos = new HashMap<String, WriteHandler>();

	public InterfaceContext getInterfaceContext() {
		return interfaceContext;
	}

	public void setInterfaceContext(InterfaceContext interfaceContext) {
		this.interfaceContext = interfaceContext;
	}

	public Map<String, WriteHandler> getWriteHandlerInfos() {
		return writeHandlerInfos;
	}

	public void setWriteHandlerInfos(Map<String, WriteHandler> writeHandlerInfos) {
		this.writeHandlerInfos = writeHandlerInfos;
	}

	/**
	 * Prototype between client and server
	 */
	public enum ResponseType {
		HTTP("HTTP", HttpResponseWriteHandler.class), WEBSOCKET("WEBSOCKET",
				WebsocketWriteHandler.class);

		private final String type;
		private final Class<? extends WriteHandler> clazz;

		public String getType() {
			return type;
		}

		public Class<? extends WriteHandler> getClazz() {
			return clazz;
		}

		ResponseType(String type, Class<? extends WriteHandler> clazz) {
			this.type = type;
			this.clazz = clazz;
		}
	}

	public WriteHandler getInstance(XServerHttpContextAttachment attachment) {
		String responseType = getResponseType(attachment);

		if (responseType.equals(ResponseType.HTTP.getType())) {
			responseType = HttpResponseType.INTERFACE.getType();

			if (attachment.getRequest().getPath().contains(".")) {
				responseType = HttpResponseType.FILE.getType();
			}
			if (responseType.equals(RequestType.WEBSOCKET)) {
				Channel channel = attachment.getChannelHandlerContext()
						.getChannel();
				attachment.getRequest().setChannel(channel);
				responseType = RequestType.WEBSOCKET.name();
			}
		}
		
		return writeHandlerInfos.get(responseType);
		

		
		
	}

	public String getResponseType(XServerHttpContextAttachment attachment) {
		String path = attachment.getRequest().getPath();

		InterfaceMeta interfaceMeta = interfaceContext.getInterfaceMeta(path);
		ResponseType responseType = ResponseType.HTTP;

		if (interfaceMeta != null) {
			ResponsePrototype responsePrototype = interfaceMeta.getMethod()
					.getAnnotation(ResponsePrototype.class);
			if (responsePrototype != null) {
				responseType = responsePrototype.value();
			}
		}

		return responseType.getType();
	}
}
